from tabnanny import check
from turtle import shape
import numpy as np
import pandas as pd 
from .table import simple_table

class DurbinWatson:
    
    def __init__(self, x: np.array):
        pass

def summary(data):
    """
    function `summary` provide data summary for your data.

    Parameters :
    ----------
    data : array_like (2-dimensional data)
    """

    if type(data)!=pd.DataFrame:
        data = pd.DataFrame(data)
    
    table  = simple_table(title= 'Variable Summary Tabel')
    table.add_line(style='double')
    table.add_row(['Variable', 'Mean', 'Std.Dev.', 'Min', 'Max'])
    table.add_line(style='single')

    for _, col in enumerate(data.columns):
        data_mean = np.mean(data[col])
        data_std = np.std(data[col],ddof=1)
        data_min = np.min(data[col])
        data_max = np.max(data[col])
        table.add_row([col, np.round(data_mean, 4), np.round(data_std, 4), np.round(data_min), np.round(data_max)])

    table.add_line(style='double')
    return table.__str__()

def cor(x, y, method='pearson'):
    """
    function `cor` compute the covariance between x and y 

    # issue: this function has numerical problem. 
    """
    x = np.asarray(x)
    y = np.asarray(y)
    num_example = x.shape[0]

    if x.shape[0] != y.shape[0] :
        raise ValueError("x({0}) and y({1}) should have same observations.".format(x.shape[0], y.shape[0]))


    def __spearman( x: np.array, y: np.array):
        """spearman correlation coefficient"""
        sorter_x = np.argsort(x, kind='mergesort')
        sorter_y = np.argsort(y, kind='mergesort')
        d_sq_sum = np.sum(np.power(sorter_x - sorter_y,2))
        r = 1 - 6 * d_sq_sum / (num_example * (num_example**2 - 1))
        return r
        
    def __pearson( x: np.array, y: np.array):
        """Pearson correlation coefficient"""
        r = np.sum((x - np.mean(x)) * (y - np.mean(y))) / \
                   np.sqrt(np.sum(np.power(x - np.mean(x), 2)))
        r = r / np.sqrt(np.sum(np.power(y - np.mean(y), 2)))
        return r
    if method == 'pearson':
        r = __pearson(x, y)
    elif method == 'spearman':
        r = __spearman(x, y)
    return r

def acf(x, lag):
    """
    `acf`: acf computes estimates of the autocovariance or autocorrelation function

    x : your time series data 
    lag : maximum lag at which to calculate the acf, lag should be integer.
    type : acf function give this option for compute "correlation", "covariance" and "partial"
    """
    if int(lag)!=lag:
        raise ValueError("parameter lag should be integer")
    x = np.asarray(x)
    lag = int(lag)
    mu = np.mean(x)
    acf = np.zeros(lag)
    n = len(x)
    for i in range(1, lag+1):
        r = (np.sum((x[0:-i] - mu) * (x[i:] - mu)) / (n - i)) / \
                np.var(x, ddof=1)
        acf[i-1] = r
    return acf

def cross_table(x):
    pass

def tabulate(bin, bins, na_rm = True):
    pass

def scale(x, center=True, scale=True):

    """
    scale data matrix
    center : alogical value if we set `center = True`, we return x - mean(x) for each columns.
    scale : a logical value if we set `scale = True`, we return x / std(x) for each columns.
    if we set `center = True` and `scale = True` we return (x - mean(x)) / std(x)

    Example :
    --------------

    >>> from StatLearnPack.general import scale
    >>> import numpy as np

    >>> x = np.array([1,2,3,4])
    >>> x = x.reshape(2,2)
    >>> x_new = scale(x)  # default : center = True scale = True
    >>> print("x_new :\n", x_new)

    out: 
    x_new :
    [[-1. -1.]
    [ 1.  1.]]
    """

    x = np.asarray(x)
    if center == True:
        x =  x - np.mean(x, axis=0)
    if scale == True:
        x = x / np.std(x, axis=0)
    return x